package com.ysw.spring.api_security.ras;

import com.google.common.collect.Maps;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.Map;

/**
 * @ClassName demo
 * @Description RAS 算法加密
 * @Author ysw
 * @Date 2022/4/22 17:31
 */
public class demo {

    public static void main(String[] args) throws Exception {
        Map<String, Object> rasMap = RSAUtil.getRasMap();
        String publicKey = String.valueOf(rasMap.get(RSAUtil.RSA_PUBLIC_KEY));
        String privateKey = String.valueOf(rasMap.get(RSAUtil.RSA_PRIVATE_KEY));
        String message = "你好！";
        byte[] bytesPub = RSAUtil.encryptPublicKey(message.getBytes("UTF-8"), publicKey);
        // base64加密后的
        String s = RSAUtil.encodeBase64(bytesPub);
        byte[] bytes = RSAUtil.decryptPrivateKey(RSAUtil.decodeBase64(s), privateKey);
        System.out.println(s);
        System.out.println(new String(bytes,"UTF-8"));
    }

    static class RSAUtil {

        private static final String ALGORITHM = "RSA";

        public static final String RSA_PUBLIC_KEY = "public_key";
        public static final String RSA_PRIVATE_KEY = "private_key";

        public static Map<String,Object> getRasMap() throws  NoSuchAlgorithmException {
            KeyPair keyPair = buildKeyPair();
            PublicKey publicKey = keyPair.getPublic();
            PrivateKey privateKey = keyPair.getPrivate();
            Map<String, Object> map = Maps.newHashMap();
            map.put(RSA_PUBLIC_KEY,encodeBase64(publicKey.getEncoded()));
            map.put(RSA_PRIVATE_KEY, encodeBase64(privateKey.getEncoded()));
            return map;
        }


        private static KeyPair buildKeyPair() throws NoSuchAlgorithmException {
            final int size = 2048;
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM);
            keyPairGenerator.initialize(size);
            KeyPair keyPair = keyPairGenerator.genKeyPair();
            return keyPair;
        }

        /**
         * 使用私钥对数据进行加密
         */
        public static byte[] encryptPrivateKeyReturnBytes(byte[] binaryData, String privateKey) throws Exception {
            Cipher cipher = getCipher(privateKey);
            return cipher.doFinal(binaryData);
        }
        /**
         * 使用私钥对数据进行加密
         */
        public static String encryptPrivateKeyReturnString(byte[] binaryData, String privateKey) throws Exception {
            Cipher cipher = getCipher(privateKey);
            return new String(cipher.doFinal(binaryData),"UTF-8");
        }


        private static Cipher getCipher(String privateKey) throws NoSuchAlgorithmException,
                InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException {
            byte[] keyBytes = decodeBase64(privateKey);
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
            // 获取RSA算法实例
            KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
            Key priKey = keyFactory.generatePrivate(keySpec);
            // 初始化加密器
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(Cipher.ENCRYPT_MODE, priKey);
            return cipher;
        }
        /**
         * 使用公钥对数据进行加密
         */
        public static byte[] encryptPublicKey(byte[] binaryData, String publicKey) throws Exception {
            byte[] keyBytes = decodeBase64(publicKey);
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
            // 获取RSA算法实例
            KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
            Key pubKey = keyFactory.generatePublic(keySpec);
            // 初始化加密器
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(Cipher.ENCRYPT_MODE, pubKey);
            return cipher.doFinal(binaryData);
        }
        /**
         * 使用私钥对数据进行解密
         */
        public static byte[] decryptPrivateKey(byte[] binaryData, String privateKey) throws Exception {
            byte[] keyBytes = decodeBase64(privateKey);
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);

            // 获取RSA算法实例
            KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
            Key priKey = keyFactory.generatePrivate(keySpec);

            // 初始化加密器
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(Cipher.DECRYPT_MODE, priKey);
            return cipher.doFinal(binaryData);
        }

        /**
         * 使用公钥对数据进行解密
         */
        public static byte[] decryptPublicKey(byte[] binaryData, String publicKey) throws Exception {
            byte[] keyBytes = decodeBase64(publicKey);
            X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);

            // 获取RSA算法实例
            KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
            Key pubKey = keyFactory.generatePublic(x509KeySpec);

            // 初始化加密器
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(Cipher.DECRYPT_MODE, pubKey);
            return cipher.doFinal(binaryData);
        }

        public static String encodeBase64(byte[] data) {
            return Base64.getEncoder().encodeToString(data);
        }

        public static byte[] decodeBase64(String decodeStr) {
            return Base64.getDecoder().decode(decodeStr);
        }


    }
}